package com.cb2.algorithm.leetcode;

/**
 * <a href='https://leetcode.cn/problems/palindrome-linked-list/'>回文链表(Palindrome Linked List)</a>
 * <p>给你一个单链表的头节点 head ，请你判断该链表是否为回文链表。如果是，返回 true ；否则，返回 false 。 </p>
 *
 * <p>
 * <b>示例：</b>
 * <pre>
 * 示例 1：
 *      输入：head = [1,2,2,1]
 *      输出：true
 *
 * 示例 2：
 *      输入：head = [1,2]
 *      输出：false
 * </pre>
 * </p>
 *
 * <p>
 * <b>提示：</b>
 *     <ul>
 *         <li>链表中节点数目在范围[1, 10^5] 内</li>
 *         <li>0 <= Node.val <= 9</li>
 *     </ul>
 * </p>
 *
 * <b>进阶：你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题？</b>
 *
 * @author c2b
 * @since 2023/10/31 15:34
 */
public class LC0234PalindromeLinkedList_S {
    static class Solution {

        public boolean isPalindrome(ListNode head) {
            if (head == null || head.next == null) {
                return true;
            }
            ListNode slow = head;
            ListNode fast = head;
            // 通过快慢指针获取中间节点的前一个节点。
            // 如果是奇数个节点，获取中间的。如果是偶数个节点，获取中间前面的。
            // 例如： 1,2,3,4,5==>3    1,2,3,4==>2
            while (fast.next != null && fast.next.next != null) {
                slow = slow.next;
                fast = fast.next.next;
            }
            ListNode firstListHead = head;
            // 此时 slow 位于第一段链表的尾节点,slow.next位于第二段链表的head，反转第二段链表
            ListNode secondListHead = reserve(slow.next);
            while (secondListHead != null) {
                if (firstListHead.val != secondListHead.val) {
                    return false;
                }
                firstListHead = firstListHead.next;
                secondListHead = secondListHead.next;
            }
            return true;
        }

        private ListNode reserve(ListNode head) {
            if (head == null) {
                return null;
            }
            ListNode prevNode = null;
            ListNode currNode = head;
            ListNode nextNode;
            while (currNode != null) {
                nextNode = currNode.next;
                currNode.next = prevNode;
                prevNode = currNode;
                currNode = nextNode;
            }
            return prevNode;
        }
    }
}